package com.example.a02glide.utils;

import android.app.Activity;
import android.view.View;

import androidx.fragment.app.FragmentActivity;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.time.temporal.ValueRange;

/**
 * *******************************************************
 * Author: chinadragon
 * Time: 8/29/21 1:41 PM
 * Name:
 * Overview:
 * Usage:
 *
 *
 * Android中的自定义注解（反射实现-运行时注解）
 * https://blog.csdn.net/tongseng/article/details/72859162
 *
 * *******************************************************
 */
public class CustomInject {

    public static void initCustomInject(FragmentActivity activity) {
        Class parentClass = activity.getClass();
        if (parentClass.isAnnotationPresent(ContentViewInject.class)) {
            ContentViewInject contentViewInject = (ContentViewInject) parentClass.getAnnotation(ContentViewInject.class);
            if (contentViewInject != null && contentViewInject.value() != 0) {
                int layoutResID = contentViewInject.value();
                try {
                    Method setContentViewMethod = parentClass.getMethod("setContentView", int.class);
                    setContentViewMethod.setAccessible(true);
                    setContentViewMethod.invoke(activity, layoutResID);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            }
        }


        Field[] fields = parentClass.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ViewInject.class)) {
                ViewInject viewInject = field.getAnnotation(ViewInject.class);
                if (viewInject != null && viewInject.value() != 0)  {
                    int viewId = viewInject.value();
                    try {

                        Method findViewById = parentClass.getMethod("findViewById", int.class);
                        findViewById.setAccessible(true);
                        Object resView = findViewById.invoke(activity, viewId);

                        field.setAccessible(true);
                        field.set(activity,resView);

                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }

            }
        }

        Method[] methods = parentClass.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(OnClick.class)) {
                OnClick onClick = method.getAnnotation(OnClick.class);
                int[] viewIds = onClick.value();
                EventBase eventBase = onClick.annotationType().getAnnotation(EventBase.class);
                String listenerSetter = eventBase.listenerSetter();
                Class listenerType = eventBase.listenerType();
                String methodName = eventBase.methodName();

                DynamicHandler dynamicHandler = new DynamicHandler(activity);
                Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, dynamicHandler);

                dynamicHandler.addMethod(methodName,method);

                for (int viewId : viewIds) {
                    Method findViewById = null;
                    try {
                        findViewById = parentClass.getMethod("findViewById", int.class);
                        findViewById.setAccessible(true);
                        View view = (View) findViewById.invoke(activity, viewId);

                        Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
                        setEventListenerMethod.setAccessible(true);
                        setEventListenerMethod.invoke(view, listener);

                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }

                }
            }
        }


    }
}
